home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 90 / CD Actual 90.iso / Software3D / K-3D / k3d-0.4.2.1 / shaders / k3d_smoke.sl < prev    next >
Encoding:
Text File  |  2004-07-23  |  4.4 KB  |  133 lines

  1. /**************************************************************************
  2.  * smoke.sl
  3.  *
  4.  * Description:
  5.  *    This is a volume shader for smoke.  Trapezoidal integration is
  6.  *    used to find scattering and extinction.
  7.  *
  8.  * Parameters:
  9.  *   opacdensity - overall smoke density control as it affects its ability
  10.  *          to block light from behind it.
  11.  *   lightdensity - smoke density control as it affects light scattering
  12.  *          toward the viewer.
  13.  *   integstart, integend - bounds along the viewing ray direction of the
  14.  *          integration of atmospheric effects.
  15.  *   stepsize - step size for integration
  16.  *   smokefreq, smokeoctaves, smokevary - control the fBm of the noisy smoke
  17.  *          If either smokeoctaves or smokevary is 0, there is no noise
  18.  *          to the smoke.
  19.  *   scatter - when non-1, can be used to give wavelength-dependent
  20.  *          extinction coefficients.
  21.  *
  22.  * Author: Larry Gritz
  23.  *
  24.  * $Revision: 1.1 $     $Date: 2002/11/25 20:24:00 $
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include "k3d_noises.h"
  29.  
  30. /* For point P (we are passed both the current and shader space
  31.  * coordinates), gather illumination from the light sources and
  32.  * compute the smoke density at that point.  Only count lights tagged
  33.  * with the "__foglight" parameter.  
  34.  */
  35. void smokedensity(point Pcur, Pshad;
  36.           uniform float smokevary, smokefreq, smokeoctaves;
  37.           float stepsize;
  38.           output color Lscatter; output float smoke)
  39. {
  40.   Lscatter = 0;
  41.   illuminance(Pcur)
  42.   {
  43.     extern color Cl;
  44.     float foglight = 1;
  45.     lightsource("__foglight", foglight);
  46.     if(foglight > 0)
  47.       Lscatter += Cl;
  48.   }
  49.   if(smokeoctaves > 0 && smokevary > 0)
  50.     {
  51.       point Psmoke = Pshad * smokefreq;
  52. #pragma nolint
  53.       smoke = snoise(Psmoke);
  54.       /* Optimize: one octave only if not lit */
  55.       if(comp(Lscatter, 0) + comp(Lscatter, 1) + comp(Lscatter, 2) > 0.01)
  56.     smoke +=
  57.       0.5 * fBm(Psmoke * 2, stepsize * 2, smokeoctaves - 1, 2, 0.5);
  58.       smoke = smoothstep(-1, 1, smokevary * smoke);
  59.     }
  60.   else
  61.     {
  62.       smoke = 0.5;
  63.     }
  64. }
  65.  
  66.  
  67.  
  68. /* Return a component-by-component exp() of a color */
  69. color
  70. colorexp(color C)
  71. {
  72.   return color(exp(comp(C, 0)), exp(comp(C, 1)), exp(comp(C, 2)));
  73. }
  74.  
  75.  
  76.  
  77. volume k3d_smoke(float opacdensity = 1, lightdensity = 1;
  78.          float integstart = 0, integend = 100;
  79.          float stepsize = 0.1, maxsteps = 100;
  80.          color scatter = 1;    /* for sky, try (1, 2.25, 21) */
  81.          float smokeoctaves = 0, smokefreq = 1, smokevary = 1;)
  82. {
  83.   point Worigin = P - I;    /* Origin of volume ray */
  84.   point origin = transform("shader", Worigin);
  85.   float dtau, last_dtau;
  86.   color li, last_li;
  87.  
  88.   /* Integrate forwards from the start point */
  89.   float d = integstart + random() * stepsize;
  90.   vector IN = normalize(vtransform("shader", I));
  91.   vector WIN = vtransform("shader", "current", IN);
  92.  
  93.   /* Calculate a reasonable step size */
  94.   float end = min(length(I), integend) - 0.0001;
  95.   float ss = min(stepsize, end - d);
  96.   /* Get the in-scattered light and the local smoke density for the
  97.    * beginning of the ray 
  98.    */
  99.   smokedensity(Worigin + d * WIN, origin + d * IN, smokevary, smokefreq,
  100.            smokeoctaves, ss, last_li, last_dtau);
  101.  
  102.   color Cv = 0, Ov = 0;        /* color & opacity of volume that we accumulate */
  103.   while(d <= end)
  104.     {
  105.       /* Take a step and get the local scattered light and smoke density */
  106.       ss = clamp(ss, 0.005, end - d);
  107.       d += ss;
  108.       smokedensity(Worigin + d * WIN, origin + d * IN, smokevary, smokefreq,
  109.            smokeoctaves, ss, li, dtau);
  110.  
  111.       /* Find the blocking and light scattering contribution of 
  112.        * the portion of the volume covered by this step.
  113.        */
  114.       float tau = opacdensity * ss / 2 * (dtau + last_dtau);
  115.       color lighttau =
  116.     lightdensity * ss / 2 * (li * dtau + last_li * last_dtau);
  117.  
  118.       /* Composite with exponential extinction of background light */
  119.       Cv += (1 - Ov) * lighttau;
  120.       Ov += (1 - Ov) * (1 - colorexp(-tau * scatter));
  121.       last_dtau = dtau;
  122.       last_li = li;
  123.     }
  124.  
  125.   /* Ci & Oi are the color and opacity of the background element.
  126.    * Now Cv is the light contributed by the volume itself, and Ov is the
  127.    * opacity of the volume, i.e. (1-Ov)*Ci is the light from the background
  128.    * which makes it through the volume.  So just composite!
  129.    */
  130.   Ci = Cv + (1 - Ov) * Ci;
  131.   Oi = Ov + (1 - Ov) * Oi;
  132. }
  133.